package com.coffee.wakeonlan.utils;

import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.coffee.wakeonlan.dao.MachineDao;
import com.coffee.wakeonlan.entity.Machine;
import com.coffee.wakeonlan.entity.User;
import com.coffee.wakeonlan.service.MachineService;

@Component
public class MulticastUtil {
	private Logger log=LoggerFactory.getLogger(MulticastUtil.class);
	/**
	 * @param args
	 * @throws Exception
	 */

	// 广播地址
	private static String BROADCAST_IP ;// 广播IP
	private static int BROADCAST_INT_PORT; // 不同的port对应不同的socket发送端和接收端
	
	private MachineService machineService;
	
	MulticastSocket broadSocket;// 用于接收广播信息

	InetAddress broadAddress;// 广播地址

	DatagramSocket sender;// 数据流套接字 相当于码头，用于发送信息

	public MulticastUtil() {
		try { 
			InputStream in = getClass().getResourceAsStream("/wakeonlan.properties");
			Properties p = new Properties();
			p.load(in);
			BROADCAST_IP=p.getProperty("BROADCAST_IP", "230.0.0.1");
			BROADCAST_INT_PORT=Integer.valueOf(p.getProperty("BROADCAST_INT_PORT", "40005"));
			// 初始化
			broadSocket = new MulticastSocket(BROADCAST_INT_PORT);
			broadAddress = InetAddress.getByName(BROADCAST_IP);
			sender = new DatagramSocket();
//			
			log.info("初始化完毕");
		} catch (Exception e) {
			// TODO: handle exception
			log.error("*****lanSend初始化失败*****" + e.toString());
		}
	}

	void join() {
		try {
			broadSocket.joinGroup(broadAddress); // 加入到组播地址，这样就能接收到组播信息
			new Thread(new GetPacket()).start(); // 新建一个线程，用于循环侦听端口信息
		} catch (Exception e) {
			// TODO: handle exception
			log.error("*****加入组播失败*****");
		}

	}

	// 定向广播发送命令
	public void sendCommond(String ip,String commond) {
		byte[] b = new byte[1024];
		DatagramPacket packet; // 数据包，相当于集装箱，封装信息
		try {
			b = ("commond@" + ip + "@" + commond).getBytes();
			packet = new DatagramPacket(b, b.length, broadAddress, BROADCAST_INT_PORT); // 广播信息到指定端口
			sender.send(packet);
			log.info("*****已发送命令请求*****");
		} catch (Exception e) {
			log.error("*****发送命令请求出错*****");
		}
	}

	//检测代理客户端存活情况
	void checkAlive() {
		byte[] b = new byte[1024];
		DatagramPacket packet;
		try {
			InetAddress addr = InetAddress.getLocalHost();
			String myip=addr.getHostAddress().toString();
			b = ("requestheartbeat@" + myip).getBytes();
			packet = new DatagramPacket(b, b.length, broadAddress, BROADCAST_INT_PORT);
			sender.send(packet);
			log.info("*****已发送检测心跳包请求*****");
		} catch (Exception e) {
			log.error("*****发送检测心跳包请求异常*****");
		}
	}

	class GetPacket implements Runnable { // 新建的线程，用于侦听
		public void run() {
			DatagramPacket inPacket;
			String[] message;
			while (true) {
				try {
					inPacket = new DatagramPacket(new byte[1024], 1024);
					broadSocket.receive(inPacket); // 接收广播信息并将信息封装到inPacket中
					message = new String(inPacket.getData(), 0, inPacket.getLength()).split("@"); // 获取信息，并切割头部，判断是何种信息（find--上线，retn--回答，offl--下线）
					InetAddress addr = InetAddress.getLocalHost();
					String ip=addr.getHostAddress().toString();
//					if (message[1].equals(ip))
//						continue; // 忽略自身
					if(message[0].equals("heartbeat")){
						log.info("主机心跳：" + " ip：" + message[1] +"MAC:"+message[2]+ " 主机：" + message[3]+ " 系统类型：" + message[4]);
						String macString=message[2];
						List<String> macs=Arrays.asList(macString.split(";"));
						List<Machine> machines= machineService.findByMacs(macs);
						if (machines==null||machines.isEmpty()) {
							Machine machine=new Machine();
							machine.setName(message[3]);
							machine.setMac(message[2]);
							machine.setHostName(message[3]);
							machine.setIp(message[1]);
							machine.setOsType(message[4]);
							machine.setIsAlive(true);
							User user=machineService.findByLoginName("admin");
							machine.setUserId(user.getId());
							machineService.add(machine);
						}else{
							Machine machine=machines.get(0);
							machine.setMac(message[2]);
							machine.setHostName(message[3]);
							machine.setIp(message[1]);
							machine.setOsType(message[4]);
							machine.setIsAlive(true);
							machineService.add(machine);
						}
					}

				} catch (Exception e) {
					e.printStackTrace();
					log.error("线程出错 " + e);
				}
			}
		}
	}
	class CheckAlive implements Runnable { // 新建的线程，用于侦听
		public void run() {
			while (true) {
				try {
					machineService.offlineAll();
					checkAlive();
					Thread.sleep(60*1000);//休眠一分钟
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public MachineService getMachineService() {
		return machineService;
	}

	@Autowired(required=true)
	public void setMachineService(MachineService machineService) {
		this.machineService = machineService;
		this.join();
		new Thread(new CheckAlive()).start(); // 新建一个线程，用于定时发送心跳
	}
	
	
}